package cn.cangfei.massage.service.impl;

import cn.cangfei.massage.dto.*;
import cn.cangfei.massage.dto.param.VisitAppointmentParam;
import cn.cangfei.massage.dto.update.UserBasicInfoUpdate;
import cn.cangfei.massage.dto.update.VisitAppointmentInfo;
import cn.cangfei.massage.dto.update.VisitAppointmentWithDoctor;
import cn.cangfei.massage.entity.*;
import cn.cangfei.massage.mapper.VisitAppointmentMapper;
import cn.cangfei.massage.service.*;
import cn.cangfei.massage.utils.HttpUtils;
import cn.cangfei.massage.utils.SmsUtils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * @author Lemon  2313812755@qq.com
 * @date 2023/3/19
 */
@Slf4j
@Service
public class VisitAppointmentServiceImpl implements IVisitAppointmentService {

    private static final int TIME_OF_ONE_TIME_PERIOD = 30;
    private static final int MAX_PEOPLE_OF_TIME_PERIOD = 5;

    @Resource
    private IUserBasicInfoService userBasicInfoService;

    @Resource
    private VisitAppointmentMapper appointmentMapper;

    @Resource
    private IVisitPlanService visitPlanService;

    @Resource
    private IPowerAccountService powerAccountService;

    @Resource
    private IMassageClinicService massageClinicService;

    @Resource
    private IUserMedicalCardService userMedicalCardService;


    @Resource
    private IUserCaseService userCaseService;

    @Resource
    private IMassageDoctorService doctorService;

    @Resource
    private IMassageInfoService massageInfoService;

    @Resource
    private RedissonClient redissonClient;


    /**
     * 获取已取号的数目
     *
     * @param planId     出诊编号
     * @param timePeriod 时间段
     * @return 已取号数目
     */
    @Override
    public int countByPlanId(Long planId, Integer timePeriod) {
        VisitAppointmentExample example = new VisitAppointmentExample();

        example.createCriteria().andPlanIdEqualTo(planId).andTimePeriodEqualTo(timePeriod)
                // 除了取消预约外
                .andStatusNotEqualTo(AppointmentEnum.CANCEL.getStatus());

        return (int) appointmentMapper.countByExample(example);
    }

    /**
     * 预约
     *
     * @param param 就诊预约参数
     * @return 是否成功
     */
    @Transactional
    @Override
    public boolean insert(String name, VisitAppointmentParam param, Integer countMax, Long hospId) {
        // 使用redisson上锁
        RLock lock = redissonClient.getLock("yuyue");
        //获取锁
        boolean flag = lock.tryLock();
        if (!flag) {
            throw new RuntimeException("预约失败请刷新");
        }
        try {
            // 根据openId查询userId
            UserBasicInfo user1 = userBasicInfoService.getUserByOpenId(name);
            Long user1Id = user1.getId();


            // 先去查看这个这一天预约的次数有没有超过count次
            LambdaQueryWrapper<VisitAppointment> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(VisitAppointment::getDay, param.getDay());
            // 只要你是预约了并且没有取消的还没有迟到的就不能预约了
            wrapper1.eq(VisitAppointment::getStatus, 0);
            wrapper1.eq(VisitAppointment::getUserId, user1Id);
            wrapper1.eq(VisitAppointment::getHospId, hospId);
            Integer appointMentCount = appointmentMapper.selectCount(wrapper1);
            if (Objects.equals(appointMentCount, countMax)) {
                throw new RuntimeException("今天的预约次数已经超过了" + countMax + "次");
            }

            // 先去查询这个时间段有没有被预约
            LambdaQueryWrapper<VisitAppointment> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(VisitAppointment::getTimePeriod, param.getTimePeriod());
            wrapper.eq(VisitAppointment::getDay, param.getDay());
            wrapper.eq(VisitAppointment::getDoctorId, param.getDoctorId());
            ArrayList<Integer> arrayList = new ArrayList<>();
            arrayList.add(1);
            arrayList.add(0);
            /*
             wrapper.and(i -> i.in(VisitAppointment::getStatus, arrayList));
             */

            // wrapper.in(VisitAppointment::getStatus, arrayList);

            List<VisitAppointment> list = appointmentMapper.selectList(wrapper);
            List<VisitAppointment> collect = new ArrayList<>();
            if (list != null && !list.isEmpty()) {
                // 进行过滤处理
                collect = list.stream().filter(visitAppointment -> visitAppointment.getStatus() == 0 || visitAppointment.getStatus() == 1).collect(Collectors.toList());

            }
            // collect就表示看看有没有被预约的
            if (!collect.isEmpty()) {
                // 表示无法预约
                throw new RuntimeException("已经被预约了");
            }


            Optional<PowerAccount> powerAccount = powerAccountService.getByName(name);
            if (!powerAccount.isPresent()) {
                return false;
            }

            PowerAccount account = powerAccount.get();

            // 根据account的openId获取到userId
            String accountName = account.getName();
            UserBasicInfo user = userBasicInfoService.getUserByOpenId(accountName);


            // 根据师傅id获取到师傅的信息看师傅是否存在
            Long doctor_id = param.getDoctorId();
            boolean count = doctorService.count(doctor_id);
            if (!count) {
                throw new RuntimeException("师傅不存在");
            }

            VisitAppointment appointment = new VisitAppointment();
            appointment.setUserId(user.getId());
            BeanUtils.copyProperties(param, appointment);
            // 获取当时的时间段
            String duan = visitPlanService.getDuan(param.getDoctorId());
            // 获取属于哪个时间段
            // TODO
            try {
                duan = duan.split(",")[param.getTimePeriod() - 1];
            } catch (Exception e) {
                throw new RuntimeException("时间段不存在");
            }

            appointment.setTime(duan);
            appointment.setDay(param.getDay());
            appointment.setTixing(0L);
            appointment.setGmtCreate(new Date());
            appointment.setGmtModified(new Date());
            appointment.setStatus(0);
            appointment.setHospId(hospId);
            int selective = appointmentMapper.insert(appointment);
//        int selective = appointmentMapper.insertSelective(appointment);
            if (selective > 0) {
                // 表示添加成功
                Long doctorId = param.getDoctorId();
                // 根据doctorId获取到师傅的openId
                Optional<MassageDoctor> optional = doctorService.getOptional(doctorId);
                if (optional.isPresent()) {
                    MassageDoctor massageDoctor = optional.get();
                    String openId = massageDoctor.getOpenId();
                }

            }


            return selective > 0;
        } finally {
            // 因为开启了多线程的
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }

    }

    /**
     * 更新预约状态
     *
     * @param id     预约编号
     * @param status 预约状态 0：未开始，1：未按时就诊，2：取消预约挂号，3：已完成
     * @return 是否成功
     */
    @Override
    public boolean update(Long id, Integer status) {
        VisitAppointment appointment = new VisitAppointment();

        appointment.setId(id);
        appointment.setStatus(status);
        appointment.setGmtModified(new Date());

        return appointmentMapper.updateByPrimaryKeySelective(appointment) > 0;
    }

    /**
     * 获取预约详情
     *
     * @param id 预订编号
     * @return 预定信息
     */
    @Override
    public Optional<VisitAppointment> getOptional(Long id) {
        return Optional.ofNullable(appointmentMapper.selectByPrimaryKey(id));
    }

    /**
     * 获取失信记录（取消+迟到）
     *
     * @param cardId   预约编号
     * @param pageNum  第-几页
     * @param pageSize 页大小
     * @return 失信记录（取消+迟到）
     */
    @Override
    public List<VisitAppointment> listMiss(Long cardId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);

        VisitAppointmentExample example = new VisitAppointmentExample();

        // 倒序从近到远
        example.setOrderByClause("gmt_create desc");

        VisitAppointmentExample.Criteria criteria = example.createCriteria();

        // 获取迟到和取消
        criteria.andStatusNotEqualTo(AppointmentEnum.WAITING.getStatus()).andStatusNotEqualTo(AppointmentEnum.FINISH.getStatus());

        if (cardId != null) {
            criteria.andCardIdEqualTo(cardId);
        }

        return appointmentMapper.selectByExample(example);
    }

    /**
     * 获取预约记录
     *
     * @param userName 用户名称
     * @param status   预约状态 0：未开始，1：未按时就诊，2：取消预约挂号，3：已完成
     * @param pageNum  第几页
     * @param pageSize 页大小
     * @return 预约记录
     */
    @Override
    public List<VisitAppointment> list(String userName, Integer status, Integer pageNum, Integer pageSize) {

        PageHelper.startPage(pageNum, pageSize);

        VisitAppointmentExample example = new VisitAppointmentExample();

        // 倒序从近到远
        example.setOrderByClause("gmt_create desc");

        VisitAppointmentExample.Criteria criteria = example.createCriteria();

        // 查询到包含这个userName的全部用户编号
        List<UserBasicInfo> userBasicInfoList = userBasicInfoService.getUserListByUserName(userName);
        if (userBasicInfoList.isEmpty()) {
            return new ArrayList<>();
        }
        List<Long> userIds = userBasicInfoList.stream().map(item -> {
            Long id = item.getId();
            return id;
        }).collect(Collectors.toList());

        if (status != null) {
            criteria.andStatusEqualTo(status);
        }

        List<VisitAppointment> appointments = appointmentMapper.selectByExample(example);
        if (appointments.size() == 0) {
            return appointments;
        }
        List<VisitAppointment> collect = appointments.stream().filter(item -> {
            return userIds.contains(item.getUserId());
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 判断预订是否存在
     *
     * @param id 预定编号
     * @return 是否存在
     */
    @Override
    public boolean count(Long id) {
        VisitAppointmentExample example = new VisitAppointmentExample();

        example.createCriteria().andIdEqualTo(id);

        return appointmentMapper.countByExample(example) > 0;
    }

    /**
     * 判断是否，已预约
     *
     * @param cardId 就诊卡号
     * @param planId 出诊编号
     * @return 是否存在
     */
    @Override
    public boolean count(Long cardId, Long planId) {
        VisitAppointmentExample example = new VisitAppointmentExample();

        example.createCriteria().andCardIdEqualTo(cardId)
                // 同一出诊中，除取消预约外
                .andStatusNotEqualTo(AppointmentEnum.CANCEL.getStatus()).andPlanIdEqualTo(planId);

        return appointmentMapper.countByExample(example) > 0;
    }

    /**
     * 获取当月信用情况
     *
     * @param accountId 账号编号
     * @param cardId    就诊卡编号
     * @return 当月信用情况
     */
    @Override
    public UserCreditDTO getCurrentCredit(Long accountId, Long cardId) {

        Date date = new Date();

        List<VisitAppointment> list = listAppointmentByDate(cardId, accountId, DateUtil.beginOfMonth(date), DateUtil.endOfMonth(date));

        if (CollUtil.isEmpty(list)) {
            return null;
        }

        return getCredit(list);
    }

    /**
     * 获取全部信用情况
     *
     * @param accountId 账号编号
     * @param cardId    就诊卡
     * @return 用户全部信用信息
     */
    @Override
    public UserCreditDTO getAllCredit(Long accountId, Long cardId) {

        VisitAppointmentExample example = new VisitAppointmentExample();

        example.setDistinct(true);

        Date date = new Date();

        example.createCriteria().andGmtCreateLessThanOrEqualTo(date).andAccountIdEqualTo(accountId);

        example.or().andCardIdEqualTo(cardId);

        List<VisitAppointment> list = appointmentMapper.selectByExample(example);

        if (CollUtil.isEmpty(list)) {
            return null;
        }

        return getCredit(list);

    }

    /**
     * 获取就诊排队序号
     *
     * @param appointment 预约记录
     * @return 排队号
     */
    @Override
    public int getQueueNum(VisitAppointment appointment) {

        VisitAppointmentExample example = new VisitAppointmentExample();

        // TODO 不需要去取消状态
        example.createCriteria()
                // 同一预约出诊
                .andPlanIdEqualTo(appointment.getPlanId())
                // 同一预约时间段
                .andTimePeriodEqualTo(appointment.getTimePeriod())
                // 预约时间小于等于当前记录
                .andGmtCreateLessThanOrEqualTo(appointment.getGmtCreate());

        List<VisitAppointment> list = appointmentMapper.selectByExample(example);

        // 同一时间段排前面的人数
        int peopleBeforeTimePeriod = list.size();

        // 当前时间段对应的排队号
        return MAX_PEOPLE_OF_TIME_PERIOD * (appointment.getTimePeriod() - 1) + peopleBeforeTimePeriod;
    }

    /**
     * 获取前面等待人数
     *
     * @param planId 出诊编号
     * @param cardId 就诊卡号
     * @return 等待人数
     */
    @Override
    public int getWaitPeopleNum(Long planId, Long cardId) {

        VisitAppointmentExample example = new VisitAppointmentExample();

        // 按照时间段排序
        example.setOrderByClause("time_period asc");

        example.createCriteria().andPlanIdEqualTo(planId).andStatusEqualTo(AppointmentEnum.WAITING.getStatus());

        List<VisitAppointment> list = appointmentMapper.selectByExample(example);

        return getCountNum(cardId, list);
    }

    /**
     * 获取候诊队列信息
     *
     * @param date      就诊日期
     * @param cardId    就诊卡
     * @param accountId 账号编号
     * @return 当天候诊队列
     */
    @Override
    public List<VisitAppointmentQueueDTO> listTodayQueue(Date date, Long cardId, Long accountId) {

        List<VisitAppointment> list = listAppointmentByDate(cardId, accountId, DateUtil.beginOfDay(date), DateUtil.endOfDay(date));

        if (CollUtil.isEmpty(list)) {
            return null;
        }

        // 统计
        return list.stream().distinct().map(this::convertQueue).collect(Collectors.toList());

    }

    /**
     * 获取就诊记录详情
     *
     * @param id 预约编号
     * @return 就诊记录详情
     */
    @Override
    public VisitAppointmentWithCaseDTO getVisitAppointmentWithCaseDTO(Long id) {
        VisitAppointmentWithCaseDTO dto = new VisitAppointmentWithCaseDTO();

        VisitAppointment visitAppointment = appointmentMapper.selectByPrimaryKey(id);

        BeanUtils.copyProperties(convert(visitAppointment), dto);

        // 还要获取到用户id
        Long userId = visitAppointment.getUserId();
        Optional<UserBasicInfo> optional = userBasicInfoService.getOptional(userId);
        if (optional.isPresent()) {
            UserBasicInfo userBasicInfo = optional.get();
            String child = userBasicInfo.getChild();
            dto.setName(child);
        }

        Long doctorId = visitAppointment.getDoctorId();
        Optional<MassageDoctor> optional1 = doctorService.getOptional(doctorId);
        if (optional1.isPresent()) {
            MassageDoctor massageDoctor = optional1.get();
            Long massageId = massageDoctor.getMassageId();
            Optional<MassageInfo> optional2 = massageInfoService.getOptional(massageId);
            if (optional2.isPresent()) {
                MassageInfo massageInfo = optional2.get();
                String address = massageInfo.getAddress();
                dto.setAddress(address);
            }
        }


        List<UserCase> list = userCaseService.listByAppointment(id);

        if (CollUtil.isEmpty(list)) {
            dto.setUserCase(null);
            return dto;
        }

        dto.setUserCase(list.get(0));

        return dto;
    }

    /**
     * 获取预约记录列表
     *
     * @param openId   微信编号
     * @param pageNum  第几页
     * @param pageSize 页大小
     * @return 预约记录
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<VisitAppointmentWithQueueDTO> listAllAppointment(String openId, Integer pageNum, Integer pageSize) {

        PageHelper.startPage(pageNum, pageSize);

        VisitAppointmentExample example = new VisitAppointmentExample();

        example.setOrderByClause("gmt_create desc");
        example.setDistinct(true);

        UserBasicInfo user = userBasicInfoService.getUserByOpenId(openId);


        List<VisitAppointment> list = appointmentMapper.selectByExample(example);

        if (CollUtil.isEmpty(list)) {
            return null;
        }

        // collect就表示这个用户的所有预约记录
        List<VisitAppointment> collect = list.stream().filter(item -> {
            return Objects.equals(item.getUserId(), user.getId());
        }).collect(Collectors.toList());

        // 下面我们还要进行修改

        if (CollUtil.isEmpty(collect)) {
            return null;
        }

        String nowTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
        collect.forEach(item -> {
            // 0才是位就诊
            if (item.getStatus() == 0) {

                String time = item.getTime();
                Integer timePeriod = item.getTimePeriod();

                /*
                // 获取这个师傅的的时间段
                Long doctorId = item.getDoctorId();
                String duan = visitPlanService.getDuan(doctorId);*/
//                String[] split = time.split(",");
                // 这个就是最迟的时间段
//                String yuyuezuihou = split[timePeriod - 1];
                // 获取最后那个
//                String zuiHou = yuyuezuihou.split("-")[1];
                String zuiHou = time.split("-")[1];
                String day = item.getDay();
                // 年月日+时间段
                day = day + " " + zuiHou;

                // 如果当前时间大于预约时间，就是迟到
                if (nowTime.compareTo(day) > 0) {
                    item.setStatus(1);
                    // 去更新
                    appointmentMapper.updateByPrimaryKeySelective(item);
                }

            }


        });
        return collect.stream().map(this::convertTo).collect(Collectors.toList());
    }

    /**
     * 获取预约记录列表(后台管理端，获取全部)
     *
     * @param pageNum  第几页
     * @param pageSize 页大小
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<VisitAppointmentWithQueueDTO> listAllAccountAppointment(String userName, Integer status, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);

        VisitAppointmentExample example = new VisitAppointmentExample();

        example.setOrderByClause("gmt_create desc");
        example.setDistinct(true);


        // 倒序从近到远

        VisitAppointmentExample.Criteria criteria = example.createCriteria();

        // 查询到包含这个userName的全部用户编号
        List<UserBasicInfo> userBasicInfoList = userBasicInfoService.getUserListByUserName(userName);
        if (userBasicInfoList.size() == 0) {
            return new ArrayList<>();
        }

        // list就表示所有用户的所有预约记录
        List<VisitAppointment> list = appointmentMapper.selectByExample(example);

        if (CollUtil.isEmpty(list)) {
            return null;
        }


        String nowTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
        list.forEach(item -> {
            // 0才是位就诊
            if (item.getStatus() == 0) {
                Integer timePeriod = item.getTimePeriod();

                String time = item.getTime();

                // 获取这个师傅的的时间段
                Long doctorId = item.getDoctorId();
                String duan = visitPlanService.getDuan(doctorId);
                String[] split = duan.split(",");
                // 这个就是最迟的时间段
                // 这个要进行注释因为会越界如果删了的话
//                String yuyuezuihou = split[timePeriod - 1];
                // 获取最后那个
//                String zuiHou = yuyuezuihou.split("-")[1];
                String zuiHou = time.split("-")[1];
                String day = item.getDay();
                // 年月日+时间段
                day = day + " " + zuiHou;

                // 如果当前时间大于预约时间，就是迟到
                if (nowTime.compareTo(day) > 0) {
                    // 设置为迟到
                    item.setStatus(1);
                    // 去更新
                    appointmentMapper.updateByPrimaryKeySelective(item);
                }

            }


        });
        return list.stream().map(this::convertTo).collect(Collectors.toList());
    }

    /**
     * 获取就诊记录列表（迟到+完成）
     *
     * @param openId   微信编号
     * @param pageNum  第一页
     * @param pageSize 页大小
     * @return 就诊记录列表
     */
    @Override
    public List<VisitAppointmentDTO> listNormalAppointment(String openId, Integer pageNum, Integer pageSize) {

        PageHelper.startPage(pageNum, pageSize);

        VisitAppointmentExample example = new VisitAppointmentExample();

        // 倒序从近到远
        example.setOrderByClause("gmt_create desc");

        VisitAppointmentExample.Criteria criteria = example.createCriteria();

        // 根据openId获取用户编号
        UserBasicInfo user = userBasicInfoService.getUserByOpenId(openId);


        // 获取 迟到 和 完成
        List<Integer> statusList = Stream.of(AppointmentEnum.MISSING.getStatus(), AppointmentEnum.FINISH.getStatus()).collect(Collectors.toList());

        criteria.andStatusIn(statusList);

        // 获取已完成记录情况
        List<VisitAppointment> list = appointmentMapper.selectByExample(example);


        if (CollUtil.isEmpty(list)) {
            return null;
        }
        List<VisitAppointment> collect = list.stream().filter(item -> {
            return Objects.equals(item.getUserId(), user.getId());
        }).collect(Collectors.toList());
        if (CollUtil.isEmpty(collect)) {
            return null;
        }

        return collect.stream().map(this::convert).collect(Collectors.toList());
    }

    /**
     * 获取挂号详情
     *
     * @param id 预约编号
     * @return 就诊详情
     */
    @Override
    public VisitAppointmentWithQueueDTO getAppointmentDetails(Long id) {
        Optional<VisitAppointment> optional = getOptional(id);

        return optional.map(this::convertTo).orElse(null);
    }

    @Override
    public Integer getTimePeriodByDoctorId(Long doctorId) {

        Integer timePeriod = appointmentMapper.getTimePeriodByDoctorId(doctorId);
        return timePeriod;
    }

    /**
     * 提前90分钟提醒
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    @Transactional
    @Override
    public void tixing() {
        // 获取锁
        // 幂等性
        RLock lock = redissonClient.getLock("tixing");
        lock.lock(15, TimeUnit.SECONDS);
        try {
            log.info("开始提醒");
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
            SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");

            // 必须是今天的而且没有取消的就可以
            String format = simpleDateFormat1.format(date);
            List<VisitAppointment> appointments = appointmentMapper.getAppointmentsByDay(format);

            // 先看哪些是没有发送的
            if (appointments == null) {
                return;
            }

            // 表示没有发送的
            List<VisitAppointment> collect = appointments.stream().filter(item -> {
                return item.getTixing() == 0;
            }).collect(Collectors.toList());

            if (collect.size() == 0) {
                return;
            }

            // 下面就是获取这个人预约的时间点
            List<VisitAppointmentInfo> visitAppointmentInfos = collect.stream().map((item) -> {
                VisitAppointmentInfo info = new VisitAppointmentInfo();
                BeanUtils.copyProperties(item, info);

                String time1 = item.getTime();
                // 根据师傅id时间段
                Long doctorId = item.getDoctorId();
                String duan = visitPlanService.getDuan(doctorId);
                String[] split = duan.split(",");
                Integer timePeriod = item.getTimePeriod();
                // 要先进行注释因为会越界
//                String finalTime = split[timePeriod - 1];
                // 然后获取前面那个
//                String[] strings = finalTime.split("-");

                // 这个就是预约这个时间点的最早的时间
//                String time = strings[0];
                // 这里是最新的，不用去其他表查询因为时间会有问题
                // 这里进行了修改 那么我们要修改回去
                info.setTruthTime(time1);
                time1 = time1.split("-")[0];
                info.setTime(time1);
                return info;

            }).collect(Collectors.toList());

            // visitAppointmentInfos表示这个人预约里面包含时间点
            // 这个就是时间点
            String formatted = simpleDateFormat.format(date);
            // 下面就循环遍历进行比较
            List<VisitAppointmentInfo> visitAppointmentInfos1 = visitAppointmentInfos.stream().filter((item) -> {
                // 当时最早的时间点
                String time = item.getTime();
                // 这个就是转为Date类型的开始的时间点
                try {
                    Date kaishi = simpleDateFormat.parse(time);
                    String s = simpleDateFormat.format(date);
                    // 将s的改为Date类型
                    // 当前时间点
                    Date dangqian = simpleDateFormat.parse(s);
                    long l = kaishi.getTime() - dangqian.getTime();

                    // 转为分钟
                    long min = l / 1000 / 60;
                    // 改为120分钟
                    return min <= 90 && min >= 0;
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                } finally {
                    if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                        // 解锁
                        lock.unlock();
                    }
                }


            }).collect(Collectors.toList());

            if (visitAppointmentInfos1.size() == 0) {
                return;
            }

            // visitAppointmentInfos1表示需要发送消息的

            // 这里的就是需要发送的
            List<Long> userIds = visitAppointmentInfos1.stream().map(VisitAppointment::getUserId).collect(Collectors.toList());
            List<UserBasicInfoUpdate> collect1 = visitAppointmentInfos1.stream().map(item -> {
                UserBasicInfoUpdate userBasicInfoUpdate = new UserBasicInfoUpdate();
                Integer timePeriod = item.getTimePeriod();
                Long doctorId = item.getDoctorId();
                // 设置师傅名字
                doctorService.getOptional(doctorId).ifPresent(doctor -> {
                    userBasicInfoUpdate.setDoctorName(doctor.getName());
                    Long massageId = doctor.getMassageId();
                    // 设置推拿馆地址
                    massageInfoService.getOptional(massageId).ifPresent(massage -> {
                        userBasicInfoUpdate.setAddress(massage.getAddress());
                    });
                });
                String duan = visitPlanService.getDuan(doctorId);
                Long userId = item.getUserId();
                // 根据用户id查询是用户基本信息
                Optional<UserBasicInfo> optional = userBasicInfoService.getOptional(userId);
                UserBasicInfo userBasicInfo = optional.get();
                BeanUtils.copyProperties(userBasicInfo, userBasicInfoUpdate);
                String[] split = duan.split(",");
//                String time = split[timePeriod - 1];
                // 设置这个用户预约的时间段

//                userBasicInfoUpdate.setDuan(time);
                userBasicInfoUpdate.setDuan(item.getTime());
                return userBasicInfoUpdate;
            }).collect(Collectors.toList());
            // 根据userIds查询出所有电话，然后再去basic里面查询openId就可以了
            // 根据accountId查询出所有的name
//        List<UserBasicInfo> list = userBasicInfoService.getNameByUserIds(userIds);
//        if (list == null) {
//            return;
//        }

            // TODO 最后就是调用短信接口去发送提醒
            System.out.println("userBasicInfos:" + collect1);
            //
            if (collect1.size() > 0) {
                for (UserBasicInfoUpdate userBasicInfoUpdate : collect1) {
                    // 下面这个是阿里云的
//                    send(userBasicInfoUpdate.getPhone());

                    // TODO 下面这个是腾讯云的

                    SmsUtils.sendSms(userBasicInfoUpdate.getDuan().split("-")[0], new String[]{"86" + userBasicInfoUpdate.getPhone()});
                }

            }


            // TODO 根据上面查询visitAppointmentInfos1来修改数据库，将里面提醒字段修改为1
            visitAppointmentInfos1.forEach((item) -> {
                VisitAppointment visitAppointment = new VisitAppointment();
                BeanUtils.copyProperties(item, visitAppointment);
                visitAppointment.setTixing(1L);
                // 因为我们要修改了时间所以要改回去
                visitAppointment.setTime(item.getTruthTime());
                // 修改数据库
                appointmentMapper.updateByPrimaryKey(visitAppointment);
            });
        } finally {
            // 因为开启了多线程
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }

        }


    }

    /**
     * 发送验证码消息(阿里云)
     *
     * @param phone 手机号
     */
    public void send(String phone) {
        //调用地址：http(s)://jumsendsms.market.alicloudapi.com/sms/send-upgrade
        String host = "http://dfsns.market.alicloudapi.com";
        String path = "/data/send_sms";
        String method = "POST";
        //自己的appcode
        String appcode = "d1d130adb987404ea5fd9671ac122da8";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        Map<String, String> querys = new HashMap<String, String>();

        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("phone_number", phone);
        //使用服务商提供的测试模板id
        bodys.put("template_id", "CST_ptdie100");
        bodys.put("content", "code:1234");
        try {
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //获取response的body
            System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 得到这天预约这个师傅并且没有取消的人数
     *
     * @param format
     * @param doctorId
     * @return
     */
    @Override
    public List<VisitAppointment> getYuYue(String format, Long doctorId) {
        List<VisitAppointment> list = appointmentMapper.getYuYue(format, doctorId);
        return list;
    }

    /**
     * 取消预约后要给这个师傅发送消息订阅
     *
     * @param id
     */
    @Override
    public void cancelAppointment(Long id) {
        VisitAppointment visitAppointment = appointmentMapper.selectByPrimaryKey(id);

        // TODO 判断一下当前时间点和那个预约结束点的大小，再看是否需要提醒

        Long doctorId = visitAppointment.getDoctorId();

        // 根据doctorId查询出openId
        Optional<MassageDoctor> optional = doctorService.getOptional(doctorId);
        if (optional.isPresent()) {
            // 下面就是去发送消息
            // TODO 取消预约后要给预约发送消息
        }
    }

    /**
     * @param format1
     * @param doctorId1
     * @return
     */
    @Override
    public List<VisitAppointment> getAppointmentListByToDayAndDoctorId(String format1, Long doctorId1, Long hospId) {
        LambdaQueryWrapper<VisitAppointment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(VisitAppointment::getDoctorId, doctorId1);
        lambdaQueryWrapper.eq(VisitAppointment::getDay, format1);
        lambdaQueryWrapper.eq(VisitAppointment::getHospId, hospId);
        lambdaQueryWrapper.eq(VisitAppointment::getStatus, 0);
        List<VisitAppointment> list = appointmentMapper.selectList(lambdaQueryWrapper);
        return list;
    }

    /**
     * 获取这个师傅的所有预约记录
     *
     * @param doctorId
     * @param day
     * @param status
     * @param pageNum
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public IPage<VisitAppointmentWithDoctor> listAllAppointmentWithDoctor(Long doctorId, String day, Integer status, Integer pageNum, Integer pageSize) {
        IPage<VisitAppointmentWithDoctor> visitAppointmentWithDoctorIPage = new Page<>(pageNum, pageSize);
        IPage<VisitAppointment> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<VisitAppointment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (!ObjectUtil.isEmpty(doctorId)) {
            lambdaQueryWrapper.eq(VisitAppointment::getDoctorId, doctorId);
        }
        if (!StringUtil.isEmpty(day)) {
            lambdaQueryWrapper.eq(VisitAppointment::getDay, day);
        }
        if (!ObjectUtil.isEmpty(status)) {
            lambdaQueryWrapper.eq(VisitAppointment::getStatus, status);
        }

        lambdaQueryWrapper.orderByDesc(VisitAppointment::getDay);
        lambdaQueryWrapper.orderByAsc(VisitAppointment::getTime);
        IPage<VisitAppointment> page1 = appointmentMapper.selectPage(page, lambdaQueryWrapper);
        List<VisitAppointment> records = page1.getRecords();
        if (records == null || records.size() == 0) {
            return visitAppointmentWithDoctorIPage;
        }
        // 下面就表示不为null
        List<VisitAppointmentWithDoctor> collect = records.stream().map((item) -> {
            VisitAppointmentWithDoctor visitAppointmentWithDoctor = new VisitAppointmentWithDoctor();
            BeanUtils.copyProperties(item, visitAppointmentWithDoctor);
            // 根据userId查询出name
            Long userId = item.getUserId();
            Optional<UserBasicInfo> optional = userBasicInfoService.getOptional(userId);
            if (optional.isPresent()) {
                UserBasicInfo userBasicInfo = optional.get();
                visitAppointmentWithDoctor.setChildName(userBasicInfo.getChild());
                visitAppointmentWithDoctor.setPhone(userBasicInfo.getPhone());
                visitAppointmentWithDoctor.setOpenId(userBasicInfo.getOpenId());
                Long doctorId1 = item.getDoctorId();
                Optional<MassageDoctor> optional2 = doctorService.getOptional(doctorId1);
                if (optional2.isPresent()) {
                    MassageDoctor massageDoctor = optional2.get();
                    visitAppointmentWithDoctor.setDoctorName(massageDoctor.getName());
                }
                // 根据这个TimePeriod获取这个师傅的时间段
                String duan = visitPlanService.getDuan(item.getDoctorId());
                String[] split = duan.split(",");
                // 这个要注释因为会产生越界
                String time = item.getTime();
//                String s = split[item.getTimePeriod() - 1];

                // 根据doctorId获取推拿馆地址
                Optional<MassageDoctor> optional1 = doctorService.getOptional(item.getDoctorId());
                MassageDoctor massageDoctor = optional1.get();
                Long massageId = massageDoctor.getMassageId();
                massageInfoService.getOptional(massageId).ifPresent((massageInfo) -> {
                    visitAppointmentWithDoctor.setAddress(massageInfo.getAddress());
                });

//                visitAppointmentWithDoctor.setTime(s);
                visitAppointmentWithDoctor.setTime(time);

            }
            return visitAppointmentWithDoctor;
        })/*.sorted((item1, item2) -> {
            // 先按照day降序再按照time升序
            String day1 = item1.getDay();
            String day2 = item2.getDay();
            String time1 = item1.getTime();
            String time2 = item2.getTime();
            if (day1.equals(day2)) {
                return time1.split("-")[0].compareTo(time2.split("-")[0]);
            } else {
                return day2.compareTo(day1);
            }

        })*/.collect(Collectors.toList());

        String nowTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
        // 下面就开始判断是否过期
        collect.forEach(item -> {
            // 0才是位就诊
            if (item.getStatus() == 0) {
                Integer timePeriod = item.getTimePeriod();

                // 获取这个师傅的的时间段
                Long doctorId1 = item.getDoctorId();
                String duan = visitPlanService.getDuan(doctorId1);
                String[] split = duan.split(",");
                // 这个就是最迟的时间段
                // 这个要注释因为可能会越界
//                String yuyuezuihou = split[timePeriod - 1];
                // 获取最后那个
//                String zuiHou = yuyuezuihou.split("-")[1];
                String time = item.getTime();
                String zuiHou = time.split("-")[1];
                String day1 = item.getDay();
                // 年月日+时间段
                day1 = day1 + " " + zuiHou;

                // 如果当前时间大于预约时间，就是迟到
                if (nowTime.compareTo(day1) > 0) {
                    item.setStatus(1);
                    // 去更新
                    appointmentMapper.updateByPrimaryKeySelective(item);
                }

            }

        });


        visitAppointmentWithDoctorIPage.setRecords(collect);
        visitAppointmentWithDoctorIPage.setTotal(page1.getTotal());
        return visitAppointmentWithDoctorIPage;
    }

    /**
     * 定时扫描看是否过期
     */
    // TODO 定时扫描
    @Scheduled(cron = "0 0/5 * * * ?")
    @Transactional
    @Override
    public void updateAppointmentStatusForCancel() {
        RLock lock = redissonClient.getLock("chidao");
        lock.lock(15, TimeUnit.SECONDS);
        try {
            log.info("开始定时扫描去修改过期状态");
            LambdaQueryWrapper<VisitAppointment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(VisitAppointment::getStatus, 0);
            // 获取所有的预约记录
            List<VisitAppointment> list = appointmentMapper.selectListByStatus(0);
//            List<VisitAppointment> list = appointmentMapper.selectList(lambdaQueryWrapper);

            // 遍历
            list.forEach(item -> {
                // 获取这个师傅的的时间段
                Long doctorId = item.getDoctorId();
                String duan = visitPlanService.getDuan(doctorId);
                String[] split = duan.split(",");
                // 这个就是最迟的时间段
                // 这个要注释因为可能会产生越界
//                String yuyuezuihou = split[item.getTimePeriod() - 1];
                // 获取最后那个
//                String zuiHou = yuyuezuihou.split("-")[1];
                String day1 = item.getDay();
                // 这个就是获取预约的时间点
                String time = item.getTime();

                // 年月日+时间段
//                day1 = day1 + " " + zuiHou;
                // 最后那个
                day1 = day1 + " " + time.split("-")[1];
                String nowTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
                // 如果当前时间大于预约时间，就是迟到
                if (nowTime.compareTo(day1) > 0) {
                    item.setStatus(1);
                    // 去更新
                    appointmentMapper.updateByPrimaryKeySelective(item);
                }
            });
        } finally {
            // 因为开启了多线程
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }
    }

    /**
     * 批量删除预约记录
     *
     * @param type
     * @return
     */
    @Transactional
    @Override
    public boolean deleteVisitAppointment(Integer type) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("当前时间" + df.format(new Date()));

        int month = 0;
        if (type == 1) {
            month = -1;
        } else if (type == 2) {
            month = -3;
        } else if (type == 3) {
            month = -6;
        } else if (type == 4) {
            month = -12;
        }

        //1代表为一个月    正的往前  负的为后
        Date date = stepMonth(new Date(), month);

        List<VisitAppointment> appointments = appointmentMapper.selectList(null);
        List<Long> longList = appointments.stream().filter(item -> {
            return item.getGmtCreate().before(date);
        }).map(VisitAppointment::getId).collect(Collectors.toList());

        // 下面进行批量删除
        if (longList.size() > 0) {
            int i = appointmentMapper.deleteBatchIds(longList);
            return i > 0;
        }

        return true;
    }

    @Override
    public void deleteWithPlanId(Long id) {
        LambdaQueryWrapper<VisitAppointment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(VisitAppointment::getPlanId, id);

        appointmentMapper.delete(lambdaQueryWrapper);


    }

    /**
     * 删除重复的预约记录
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    @Override
    public void deleteRepeat() {
        // 筛选出 day是大于等于今天的
        LambdaQueryWrapper<VisitAppointment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 转为年月日
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        lambdaQueryWrapper.ge(VisitAppointment::getDay, format);
        lambdaQueryWrapper.eq(VisitAppointment::getStatus, 0);
        List<VisitAppointment> list = appointmentMapper.selectList(lambdaQueryWrapper);
        if (list == null || list.isEmpty()) {
            return;
        }
        // 将里面的day收集起来
        Set<String> collect = new HashSet<>();

        Map<String, List<VisitAppointment>> strMap = new HashMap<>();
        for (VisitAppointment visitAppointment : list) {
            String day = visitAppointment.getDay();
            collect.add(day);
            List<VisitAppointment> visitAppointments = strMap.get(day);
            if (visitAppointments == null) {
                visitAppointments = new ArrayList<>();
            }
            visitAppointments.add(visitAppointment);
            strMap.put(day, visitAppointments);
        }
        Map<Long, List<VisitAppointment>> map = new HashMap<>();

        for (String day : collect) {
            // 得到当天的所有的预约记录
            List<VisitAppointment> visitAppointments = strMap.get(day);
            // 将这些预约记录按照师傅进行分组
            map = visitAppointments.stream().collect(Collectors.groupingBy(VisitAppointment::getDoctorId));

            // 然后里面的 List<VisitAppointment> 就是这个师傅当天的预约记录 我们看 period是否有重复的
            // 状态都是0的
            for (Long doctorId : map.keySet()) {
                List<VisitAppointment> visitAppointments1 = map.get(doctorId);
                if (visitAppointments1 == null || visitAppointments1.isEmpty()) {
                    continue;
                }
                // 否则我们就看是否有重复的
                clearAppointments(visitAppointments1);
            }
        }


    }

    private void clearAppointments(List<VisitAppointment> visitAppointments1) {
        // 遍历看period是否有重复
        for (int i = 0; i < visitAppointments1.size(); i++) {
            VisitAppointment visitAppointment = visitAppointments1.get(i);
            Integer period = visitAppointment.getTimePeriod();
            for (int j = i + 1; j < visitAppointments1.size(); j++) {
                VisitAppointment visitAppointment1 = visitAppointments1.get(j);
                Integer period1 = visitAppointment1.getTimePeriod();
                if (period.equals(period1)) {
                    // 说明有重复的
                    // 我们就删除这个
                    visitAppointment1.setStatus(2);
                    appointmentMapper.updateById(visitAppointment1);
                }
            }
        }

    }

    public static Date stepMonth(Date sourceDate, int month) {
        Calendar c = Calendar.getInstance();
        c.setTime(sourceDate);
        c.add(Calendar.MONTH, month);
        return c.getTime();
    }

    /**
     * 获取诊室地址
     *
     * @param doctorId 师傅编号
     * @param time     时间段：1 上午，2 下午
     * @param day      日期
     * @return 诊室地址
     */
    @Override
    public String getClinicName(Long doctorId, Integer time, Date day) {
        // 获取出诊计划
        List<VisitPlan> plans = visitPlanService.getByTimeAndDate(doctorId, time, day);

        if (CollUtil.isEmpty(plans)) {
            return null;
        }

        VisitPlan plan = plans.get(0);

        return massageClinicService.getAddress(plan.getClinicId());
    }

    /**
     * 获取预约用户信息列表
     *
     * @param doctorId 师傅编号
     * @param time     时间段：1 上午，2 下午
     * @param day      日期
     * @param pageNum  第几页
     * @param pageSize 页大小
     * @return 用户信息列表
     */
    @Override
    public List<VisitUserInfoDTO> listVisitUserInfo(Long doctorId, Integer time, Date day, Integer pageNum, Integer pageSize) {

        // 获取出诊计划
        List<VisitPlan> plans = visitPlanService.getByTimeAndDate(doctorId, time, day);

        if (CollUtil.isEmpty(plans)) {
            return null;
        }

        PageHelper.startPage(pageNum, pageSize);

        // 获取预约卡号
        VisitAppointmentExample example = new VisitAppointmentExample();

        // 根据预约时间段排序
        example.setOrderByClause("time_period asc");
        example.setOrderByClause("gmt_create desc");

        VisitAppointmentExample.Criteria criteria = example.createCriteria();
        criteria.andPlanIdEqualTo(plans.get(0).getId());

        // 筛选时间段
        if (TimePeriodEnum.AM.getTime().equals(time)) {
            criteria.andTimePeriodBetween(TimePeriodEnum.AM.getStart(), TimePeriodEnum.AM.getEnd());
        } else {
            criteria.andTimePeriodBetween(TimePeriodEnum.PM.getStart(), TimePeriodEnum.PM.getEnd());
        }

        return appointmentMapper.selectByExample(example).stream().map(this::convertToUserInfo)

                // 去除取消后的记录
                .filter(userInfo -> !AppointmentEnum.CANCEL.getStatus().equals(userInfo.getStatus())).collect(Collectors.toList());
    }

    /**
     * 转换为候诊队列
     *
     * @param appointment 预约记录信息
     * @return 候诊队列信息
     */
    private VisitAppointmentQueueDTO convertQueue(VisitAppointment appointment) {

        VisitAppointmentQueueDTO dto = new VisitAppointmentQueueDTO();

        Long userId = appointment.getUserId();
        Long planId = appointment.getPlanId();

        int queueNum = getQueueNum(appointment);
        int waitPeopleNum = getWaitPeopleNum(planId, userId);

        dto.setAppointmentId(appointment.getId());

        dto.setQueueNum(queueNum);
        dto.setWaitPeopleNum(waitPeopleNum);

        Optional<VisitPlanDTO> optional = visitPlanService.getOptional(appointment.getPlanId());

        // 获取出诊计划信息
        optional.ifPresent(visitPlanDTO -> BeanUtils.copyProperties(visitPlanDTO, dto));

        dto.setStatus(appointment.getStatus());
        dto.setName(userMedicalCardService.getName(appointment.getUserId()));

        // 假设一个时间段 30 分钟内 5 个人
        dto.setWaitTime(waitPeopleNum * (TIME_OF_ONE_TIME_PERIOD / MAX_PEOPLE_OF_TIME_PERIOD));
        dto.setTimePeriod(appointment.getTimePeriod());

        return dto;
    }

    /**
     * 转换未用户预约信息
     *
     * @param appointment 预约信息
     * @return 预约信息
     */
    private VisitUserInfoDTO convertToUserInfo(VisitAppointment appointment) {

        VisitUserInfoDTO dto = new VisitUserInfoDTO();

        // 设置就诊卡信息
        Long userId = appointment.getUserId();

        Optional<UserMedicalCard> optional = userMedicalCardService.getOptional(userId);

        if (optional.isPresent()) {
            UserMedicalCard card = optional.get();
            BeanUtils.copyProperties(card, dto);
        }

        // 预约信息
        dto.setUserId(userId);
        dto.setStatus(appointment.getStatus());
        dto.setQueueNum(getQueueNum(appointment));
        dto.setAppointmentId(appointment.getId());
        dto.setTimePeriod(appointment.getTimePeriod());
        dto.setStatus(appointment.getStatus());

        return dto;
    }

    /**
     * 获取统计数目
     *
     * @param userId 就诊卡编号
     * @param list   就诊列表
     * @return 统计数目
     */
    private int getCountNum(Long userId, List<VisitAppointment> list) {

        if (CollUtil.isEmpty(list)) {
            return 0;
        }

        // 排队人数
        int waitPeopleCount = 0;

        for (int i = 0; i < list.size(); i++) {
            if (userId.equals(list.get(i).getUserId())) {
                waitPeopleCount = i;
                break;
            }
        }

        return waitPeopleCount;
    }

    /**
     * 转换获取对应中文名称
     *
     * @param appointment 预约记录
     * @return 预约记录以及就诊用户
     */
    private VisitAppointmentDTO convert(VisitAppointment appointment) {

        VisitAppointmentDTO dto = new VisitAppointmentDTO();

        dto.setAppointmentId(appointment.getId());

        Optional<VisitPlanDTO> optional = visitPlanService.getOptional(appointment.getPlanId());

        // 获取出诊计划信息
        optional.ifPresent(visitPlanDTO -> BeanUtils.copyProperties(visitPlanDTO, dto));

        dto.setStatus(appointment.getStatus());
        dto.setName(userMedicalCardService.getName(appointment.getUserId()));

        return dto;
    }

    /**
     * 转换获取对应中文名称
     *
     * @param appointment 预约记录
     * @return 预约记录以及就诊用户
     */
    private VisitAppointmentWithQueueDTO convertTo(VisitAppointment appointment) {

        VisitAppointmentWithQueueDTO dto = new VisitAppointmentWithQueueDTO();

        BeanUtils.copyProperties(convert(appointment), dto);
        Long doctorId = appointment.getDoctorId();
        Integer timePeriod = appointment.getTimePeriod();

        // 获取时间段
        /*String duan = visitPlanService.getDuan(doctorId);
        String[] split = duan.split(",");
        int index = timePeriod - 1;*/
        String time = appointment.getTime();
//        String duanFinal = split[index];

        // 获取预约时间
        String day = appointmentMapper.getDayById(appointment.getId());

        // 将时间返回
        dto.setDuan(time);
        dto.setDay(day);

        // 设置孩子名字
        Long userId = appointment.getUserId();
        Optional<UserBasicInfo> optional = userBasicInfoService.getOptional(userId);
        UserBasicInfo userBasicInfo = optional.get();
        String child = userBasicInfo.getChild();
        dto.setName(child);

        dto.setStatus(appointment.getStatus());
        dto.setQueueNum(getQueueNum(appointment));
        dto.setGmtCreate(appointment.getGmtCreate());

        return dto;
    }

    /**
     * 统计信用情况
     *
     * @param list 就诊记录列表
     * @return 信用情况
     */
    private UserCreditDTO getCredit(List<VisitAppointment> list) {
        UserCreditDTO dto = new UserCreditDTO();

        int miss = 0, cancel = 0, finish = 0;

        Map<Integer, Long> map = list.stream().collect(Collectors.groupingBy(VisitAppointment::getStatus, Collectors.counting()));

        if (map.containsKey(AppointmentEnum.MISSING.getStatus())) {
            miss = map.get(AppointmentEnum.MISSING.getStatus()).intValue();
        }

        if (map.containsKey(AppointmentEnum.CANCEL.getStatus())) {
            cancel = map.get(AppointmentEnum.CANCEL.getStatus()).intValue();
        }

        if (map.containsKey(AppointmentEnum.FINISH.getStatus())) {
            finish = map.get(AppointmentEnum.FINISH.getStatus()).intValue();
        }

        dto.setFinish(finish);
        dto.setCancel(cancel);
        dto.setMiss(miss);

        return dto;

    }

    /**
     * 获取出诊预约情况
     *
     * @param cardId    就诊卡号
     * @param accountId 账号编号
     * @param start     开始日期
     * @param end       结束日期
     * @return 预约记录列表
     */
    private List<VisitAppointment> listAppointmentByDate(Long cardId, Long accountId, Date start, Date end) {

        List<Long> planList = visitPlanService.list(start, end);

        if (CollUtil.isEmpty(planList)) {
            return null;
        }

        VisitAppointmentExample example = new VisitAppointmentExample();

        example.setDistinct(true);

        example.createCriteria().andPlanIdIn(planList).andCardIdEqualTo(cardId);

        // 或账号编号一致
        example.or().andPlanIdIn(planList).andAccountIdEqualTo(accountId);

        return appointmentMapper.selectByExample(example);
    }
}
